# coding=utf-8

from inspect import isfunction
import traceback
from controller.controller_base import *
from dbs.models import *
from controller.entry_controller import EntryController
from controller.export_controller import ExportController
from flask import current_app
import json, os, re
from conf import constant, settings, json_map
from sqlalchemy import and_,or_
import copy

class BatchController(ControllerBase):
    map_table = {GEO_LAYER_BRIDGE: Bridge, GEO_LAYER_BUILDING: Building, GEO_LAYER_CULVERT: Culvert,
                 GEO_LAYER_DECELERATION: Deceleration, GEO_LAYER_DELINEATER: Delineater,
                 GEO_LAYER_GUARDBAR: GuardBar,
                 GEO_LAYER_ILLUMINATION: Illumination, GEO_LAYER_LANDUSE: LandUse, GEO_LAYER_ROADLINE: RoadLine,
                 GEO_LAYER_ROADPOLYGON: RoadPolygon, GEO_LAYER_ROADSIGN: RoadSign, GEO_LAYER_TREELAWN: TreeLawn,
                 GEO_LAYER_TUNNEL: Tunnel, GEO_LAYER_WATER: Water}

    def __init__(self):
        super(BatchController, self).__init__()

        self.geo_layer_map = {  # 字典表码 映射 图层名
            constant.GEO_LAYER_BRIDGE: 'bridge',
            constant.GEO_LAYER_BUILDING: 'building',
            constant.GEO_LAYER_CULVERT: 'culvert',
            constant.GEO_LAYER_DECELERATION: 'deceleration',
            constant.GEO_LAYER_DELINEATER: 'delineater',
            constant.GEO_LAYER_GUARDBAR: 'guardbar',
            constant.GEO_LAYER_ILLUMINATION: 'illumination',
            constant.GEO_LAYER_LANDUSE: 'landuse',
            constant.GEO_LAYER_ROADLINE: 'roadline',
            constant.GEO_LAYER_ROADPOLYGON: 'roadpolygon',
            constant.GEO_LAYER_ROADSIGN: 'roadsign',
            constant.GEO_LAYER_TREELAWN: 'treelawn',
            constant.GEO_LAYER_TUNNEL: 'tunnel',
            constant.GEO_LAYER_WATER: 'water'
        }

    def __db_items_to_list(self, items, func=None):
        item_list = []
        for item in items:
            if isfunction(func):
                item_dict = func(item)
            else:
                item_dict = self.serialize(item)
            item_list.append(item_dict)
        return item_list


    def get_files_list(self):
        """查看linux服务器 /data/xxxxxx/里的文件列表"""
        # result = []
        path = current_app.config['SHAPE_ENTRY_PATH']  # linux  gdb文件路径
        list_dir = os.listdir(path)  # linux 文件list
        # for linux_file_name in list_dir:
        #     if not re.search('.gdb$', linux_file_name):
        #         writelog("服务器gdb文件目录中有非gdb文件:%s  请去查看 PATH:%s " % (linux_file_name, path))
        #     elif re.search('^\.', linux_file_name):
        #         writelog("服务器gdb文件目录中有隐藏文件:%s  请去查看 PATH:%s " % (linux_file_name, path))
        #     else:
        #         result.append(linux_file_name)
        return list_dir

    def add_batch(self, user_id, sub_set_id, file_name, remark, old_srid):
        try:
            file_name = file_name
            file_path = settings.settings.get('SHAPE_ENTRY_PATH')
            # file_name = 'hf-water'    # 本地测试
            # file_path = 'D:\\data\\test_data\\'   # 本地测试

            import_file = ImportFile(
                file_name=file_name,
                file_path=file_path
            )
            db.session.add(import_file)
            db.session.commit()  # 添加完会刷新 import_file对象的属性

            extend_info = json_map.TEMP_DATA_EXTEND
            extend_info['batch_info']['sub_data_set_id'] = sub_set_id
            batch = Batch(
                user_id=user_id,
                sub_set_id=sub_set_id,
                file_id=import_file.file_id,
                remark=remark,
                srid=old_srid,
                extend_info=extend_info
            )
            db.session.add(batch)
            db.session.commit()
            batch_id = batch.batch_id

            entry_controller = EntryController(old_srid=old_srid, new_srid=GIS_SRID_WEBMERCATOR, extend_info=extend_info)
            entry_controller.entry(sub_set_id, batch_id, import_file)

            self.db.session.query(Batch).filter(Batch.batch_id == batch_id). \
                update({"extend_info": entry_controller.extend_info})
            db.session.commit()
            db.session.close()  # 结束会话
        except:
            writelog(traceback.format_exc())

    def remove_batch(self, batch_id):
        self.db.session.query(Batch).filter_by(batch_id=batch_id).update({'is_deleted': True})
        self.db.session.commit()
        self.db.session.query(TemporaryData).filter_by(batch_id=batch_id).update({'is_deleted': True})
        self.db.session.commit()
        self.db.session.close()


    def get_upload_progressbar(self, file_ids):
        """获取文件导入进度条"""
        import_progresses = self.db.session.query(ImportFile.import_progress, ImportFile.file_id, ImportFile.file_name). \
            filter(ImportFile.file_id.in_(file_ids)).all()
        result = []
        for progress in import_progresses:
            result.append({
                'import_progress': progress[0],
                'file_id': progress[1],
                'file_name': progress[2]
            })
        return result

    def get(self, batch_id):
        data = self.db.session.query(Batch).filter(Batch.batch_id == batch_id).first()
        return self.serialize(data)


    def get_list(self, data_set_id, user_id, page_size, page_index):
        batch_list = []
        batchs = db.session.query(
            Batch
            ). \
            join(SubDataSet, SubDataSet.sub_set_id == Batch.sub_set_id). \
            join(DataSet, DataSet.data_set_id==SubDataSet.data_set_id). \
            filter(
            DataSet.data_set_id == data_set_id,
            Batch.user_id == user_id,
            Batch.is_deleted == False,
            DataSet.is_deleted == False,
            SubDataSet.is_deleted == False
        ). \
            order_by(Batch.create_time.desc()).paginate(page_index, page_size, False)

        for batch in batchs.items:  # 不用 .paginate() 则是 遍历tasks,用则tasks.items
            batch_dict = self.serialize(batch)
            file = self.db.session.query(ImportFile).filter_by(file_id=batch_dict.get('file_id')).first()
            file_dict = self.serialize(file)
            batch_dict['srname'] = json_map.GIS_SRID.get(batch_dict.get('srid'))
            batch_dict['file_id'] = file_dict.get('file_id')
            batch_dict['file_name'] = file_dict.get('file_name')
            batch_dict['sub_set_name'] = SubDataSet.query.filter_by(
                sub_set_id=batch_dict.get('sub_set_id')).first().sub_set_name
            batch_dict['user_name'] = User.query.filter_by(user_id=batch_dict.get('user_id')).first().username
            batch_list.append(batch_dict)

        data = {
            'batch_list': batch_list,
            'pagination': {
                'page_index': page_index,
                'page_size': page_size,
                'page_count': batchs.pages,
                'total': batchs.total
            }
        }
        return data

    def get_data_list(self, batch_id, page_size, page_index, geo_layers, is_modified=None):
        if is_modified is None:     # 查全部
            params = [
                TemporaryData.batch_id == batch_id,
                TemporaryData.geo_layer.in_(geo_layers),
                TemporaryData.check_status != CHECK_STATUS_ABNORMAL,
                TemporaryData.is_deleted == False
            ]
        else:
            if is_modified:     # 修改
                params = [TemporaryData.batch_id == batch_id,
                          TemporaryData.geo_layer.in_(geo_layers),
                          TemporaryData.is_modify == True,
                          TemporaryData.check_status != CHECK_STATUS_ABNORMAL,
                          TemporaryData.is_deleted == False
                        ]
            else:          # 未修改
                params = [TemporaryData.batch_id == batch_id,
                          TemporaryData.geo_layer.in_(geo_layers),
                          TemporaryData.is_modify == False,
                          TemporaryData.check_status != CHECK_STATUS_ABNORMAL,
                          TemporaryData.is_deleted == False
                         ]

        datas = self.db.session.query(
                TemporaryData.data_id.label('data_id'),
                TemporaryData.gis_id.label('gis_id'),
                TemporaryData.sub_set_id.label('sub_set_id'),
                TemporaryData.geo_layer.label('geo_layer'),
                TemporaryData.geo_type.label('geo_type'),
                TemporaryData.is_modify.label('is_modified'),
                TemporaryData.geom.ST_AsGeoJSON().label('geo_json')
            ).filter(*params).paginate(page_index, page_size, False)

        data_list = []
        for data in datas.items:
            data_dict={}
            data_dict['gis_id'] = data.gis_id
            data_dict['data_id'] = data.data_id
            data_dict['geo_json'] = data.geo_json
            data_dict['geo_layer'] = data.geo_layer
            data_dict['geo_type'] = data.geo_type
            data_dict['geo_layer_name'] = self.geo_layer_map.get(data.geo_layer)
            data_dict['sub_set_id'] = data.sub_set_id
            data_dict['is_modified'] = data.is_modified

            tasks = self.db.session.query(Task.task_name.label('task_name'),
                                            Task.task_id.label('task_id'),
                                          TaskDataRelation.relation_id.label('relation_id')
                                          ).outerjoin(TaskDataRelation, TaskDataRelation.task_id == Task.task_id).\
                                    filter(
                                    TaskDataRelation.data_id == data_dict['data_id'],
                                    Task.task_status.in_([TASK_STATUS_SUBMITTED,TASK_STATUS_NEW]),
                                    Task.is_deleted==False,
                                    TaskDataRelation.is_deleted==False
                                ).all()

            def task_item_func(task):
                task_dict={}
                task_dict['task_name'] = task.task_name
                task_dict['task_id'] = task.task_id
                task_dict['relation_id'] = task.relation_id
                return task_dict

            data_dict['tasks'] = self.__db_items_to_list(tasks, task_item_func)

            geo_json = data_dict.get('geo_json')
            if geo_json is not None:
                geo_json = json.loads(geo_json)

            data_dict['geo_json'] = geo_json



            data_list.append(data_dict)

        result = {
            'batch_list': data_list,
            'pagination': {
                'page_index': page_index,
                'page_size': page_size,
                'page_count': datas.pages,
                'total': datas.total
            }
        }
        return result

    def get_real(self, batch_id, geo_layers, x_min, y_min, x_max, y_max):
        def item_func(item):
            item_dict = {}
            item_dict['geo_json'] = json.loads(item.geo_json)
            item_dict['sub_set_id'] = item.sub_set_id
            item_dict['batch_id'] = item.batch_id
            item_dict['geo_layer'] = item.geo_layer
            item_dict['gis_id'] = item.gis_id
            return item_dict

        results = self.db.session.query(
                TemporaryData.gis_id.label('gis_id'),
                TemporaryData.batch_id.label('batch_id'),
                TemporaryData.sub_set_id.label('sub_set_id'),
                TemporaryData.geo_layer.label('geo_layer'),
                TemporaryData.geom.ST_AsGeoJSON().label('geo_json')
                ).filter(
                    TemporaryData.batch_id == batch_id,
                    TemporaryData.geo_layer.in_(geo_layers),
                    func.ST_Contains(func.ST_MakeEnvelope(x_min, y_min, x_max, y_max, 3857), TemporaryData.geom)
                ).all()

        res = self.__db_items_to_list(results, item_func)
        return res

    def get_task_list(self, batch_id, user_id, page_size, page_index, status_list=[]):
        # def item_func(item):
        #     item_dict = self.serialize(item)
        #     return item_dict

        tasks = db.session.query(Task) \
            .outerjoin(Batch, Batch.batch_id == Task.batch_id) \
            .filter(Batch.batch_id == batch_id,
                    Batch.is_deleted == False,
                    Task.is_deleted == False,
                    Task.user_id == user_id,
                    Task.task_status.in_(status_list)) \
            .order_by(Task.create_time.desc()) \
            .paginate(page_index, page_size, False)

        # for task in tasks.items:
        #     task_dict = self.serialize(task)
        #     task_dict['sub_set_name'] = SubDataSet.query.filter_by(
        #         sub_set_id=task_dict.get('sub_set_id')).first().sub_set_name
        #     task_dict['user_name'] = User.query.filter_by(user_id=task_dict.get('user_id')).first().username
        #     task_list.append(task_dict)

        task_list = self.__db_items_to_list(tasks.items)

        data = {
            'task_list': task_list,
            'pagination': {
                'page_index': page_index,
                'page_size': page_size,
                'page_count': tasks.pages,
                'total': tasks.total
            }
        }
        return data